import AxisLineRenderer from "../renderer/AxisLineRenderer"
import * as THREE from "three"
import SnapAxisLine3 from "../three/SnapAxisLine3"
import Vectors from "../three/Vectors"
import se from "../math/69626"
import { measurementFeatureType } from "../enum/measurement.enum"
import SnappablePointer from "./SnappablePointer"
import MeasurementModeModule from "../module/MeasurementModeModule"
import WebGLScene from "../three/WebGLScene"
import EngineContext from "../EngineContext"
import { Subscription } from "../utils/Subscription"

export default class SnappableAxisUpdater {
  pointer: SnappablePointer
  mobile: boolean
  getPhase: MeasurementModeModule["getPhase"]
  scene: WebGLScene
  getLayer: EngineContext["getRenderLayer"]
  subscriptions: Subscription[]
  editing: boolean
  axisLines: SnapAxisLine3[]
  axisAlignmentHelper: THREE.Object3D
  updateSnapping: (e: any) => void
  axisLineRenderer: AxisLineRenderer
  constructor(e, t, i, s, n) {
    this.pointer = e
    this.mobile = t
    this.getPhase = i
    this.scene = s
    this.getLayer = n
    this.subscriptions = []
    this.editing = !1
    this.axisLines = []
    this.axisAlignmentHelper = new THREE.Object3D()
    this.updateSnapping = e => {
      this.axisLines.length > 0 && (this.pointer.removeSnapFeatures(this, measurementFeatureType.AxisAny), (this.axisLines.length = 0))
      if (e) {
        this.axisAlignmentHelper.position.copy(e.point.clone())
        const t = se.J2(this.axisAlignmentHelper, e.point.clone(), e.normal)
        this.axisAlignmentHelper.updateMatrixWorld(!0)
        const i = this.axisAlignmentHelper.matrixWorld
        const s = 100
        const n = (e: THREE.Vector3, t: THREE.Vector3, i: THREE.Matrix4, n: number) => {
          const r = new SnapAxisLine3(e.clone().multiplyScalar(s), t.clone().multiplyScalar(s), n)
          r.applyMatrix4(i)
          return r
        }
        const r = new THREE.Matrix4().copyPosition(i)
        this.axisLines.push(n(Vectors.UP, Vectors.DOWN, r, measurementFeatureType.AxisY))
        if (!t) {
          this.axisLines.push(
            n(Vectors.FORWARD, Vectors.BACK, i, measurementFeatureType.AxisY),
            n(Vectors.UP, Vectors.DOWN, i, measurementFeatureType.AxisX),
            n(Vectors.LEFT, Vectors.RIGHT, i, measurementFeatureType.AxisZ)
          )
        }
        this.axisLines.length > 0 && this.pointer.addSnapFeatures(this, measurementFeatureType.AxisAny, this.axisLines)
      }
    }
  }
  init() {}
  dispose() {}
  activate() {
    this.subscriptions.push(this.pointer.onOriginChanged(this.updateSnapping, !0))
    this.axisLineRenderer = new AxisLineRenderer(this.scene, this.getLayer("cursor-mesh"))
  }
  deactivate() {
    this.subscriptions.forEach(e => e.cancel())
    this.subscriptions.length = 0
    this.pointer.removeSnapFeatures(this, measurementFeatureType.AxisAny)
    this.axisLineRenderer.dispose()
    this.axisLineRenderer = null
  }
  beforeRender() {
    const t = !!this.mobile
    t !== this.editing && ((this.editing = t), this.axisLineRenderer.clearLines())
  }
  render() {
    this.editing && this.axisLineRenderer.render(this.pointer.lastIntersection, this.axisLines)
  }
}
